#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <functional>
#include <unistd.h>
#include <string.h>
#include "Log.hpp"
#include "Comm.hh"
#define BACKLOG 5

using namespace lyrics;
using hanlder_t = std::function<std::string(std::string)>;

const uint16_t gport = 8080;

class TcpServer
{
private:
    struct StrData
    {
        int _sockfd;
        TcpServer *_ts;
    };
public:
    TcpServer(hanlder_t hanlder,uint16_t port = gport)
    :_port(port),_isrunning(false),_handler(hanlder){}
    void InitServer()
    {
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if(_listensockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error" << strerror(_listensockfd);
            Die(SOCKET_ERR);
        }
        LOG(LogLevel::INFO) << "socket success,the socket is " << _listensockfd;
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;
        int n = ::bind(_listensockfd,CONV(&local),sizeof(local));
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error" << strerror(n);
            Die(BIND_ERR);
        }
        LOG(LogLevel::INFO) << "bind success,the socket is " << _listensockfd;
        n = ::listen(_listensockfd,BACKLOG);
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "listen error" << strerror(n);
            Die(LISTEN_ERR);
        }
        LOG(LogLevel::INFO) << "listen success,this return number is : " << n;
    }
    static void* Handler(void *args)
    {
        while(true)
        {
            StrData *data = static_cast<StrData*>(args);
            char cmdstr[1024];
            //接收消息
            int n = ::recv(data->_sockfd, cmdstr, sizeof(cmdstr) - 1, 0);
            if(n < 0)
            {
                LOG(LogLevel::FATAL) << "recv error" << strerror(n);
                continue;
            }
            cmdstr[n] = 0;
            LOG(LogLevel::INFO) << "recv success,the message is " << cmdstr;
            std::string result = data->_ts->_handler(cmdstr);
            n = ::send(data->_sockfd,result.c_str(),result.size(),0);
            if(n < 0)
            {
                LOG(LogLevel::WARNING) << "send error" << strerror(n);
            }
        }   
        return nullptr;
    }
    //启动服务器
    void Start()
    {
        _isrunning = true;
        while(_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            //等待客户端连接
            int sockfd = ::accept(_listensockfd,CONV(&peer),&len);
            if(sockfd < 0)
            {
                LOG(LogLevel::FATAL) << "accept error" << strerror(sockfd);
                continue;
            }
            LOG(LogLevel::INFO) << "accept success,the socket is " << sockfd;
            
            StrData* data = new StrData();
            data->_sockfd = sockfd;
            data->_ts = this;
            pthread_t tid;
            pthread_create(&tid,nullptr,Handler,(void*)data);
            pthread_detach(tid);
        }
    }
private:
    int _listensockfd;
    uint16_t _port;
    bool _isrunning;
    hanlder_t _handler;
};